﻿// 
//    Copyright 2010 The JaernCloud Project
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Scripting;
using System.Xml.Linq;
using System.Xml;

namespace JaernCloud.Language.Compiler.Ast {
    
    public class AstNode : AstTokenInfo {

        // Node model
        public AstTag Tag { get; set; }
        public List<AstInheritsFrom> InheritsFrom { get; set; }
        public List<AstNode> Children { get; set; }
        public AstNode Parent { get; set; }
        public Object Constant { get; set; }
        
        // Node actions
        public Boolean IsAction { get; set; }
        public Boolean IsAsync { get; set; }
        public Boolean IsAjax { get; set; }

        public AstNodeKind? Kind { get; set; }

        // Node expressions
        public AstExpression Expression { get; set; }

        // Node query operator (foreach etc.)
        public virtual AstQueryOperator Query { get; set; }

        public AstNode() {
            Children = new List<AstNode>();
            InheritsFrom = new List<AstInheritsFrom>();
            IsAction = false;
            IsAsync = false;
        }

        public string XmlRepresentation {
            get {
                StringBuilder xmlString = new StringBuilder();
                XmlWriter xml = XmlWriter.Create(xmlString, new XmlWriterSettings { Indent = true, IndentChars = "    ", OmitXmlDeclaration = true, ConformanceLevel = ConformanceLevel.Auto });
                xml.WriteStartDocument();
                WriteXmlRepresentation(xml);
                xml.WriteEndDocument();
                xml.Flush();
                return xmlString.ToString();
            }
        }

        private void WriteXmlRepresentation(XmlWriter xml) {
            xml.WriteStartElement("node");
            if (Tag != null) {
                xml.WriteAttributeString("tag", Tag.ToString());
            }
            if (InheritsFrom.Count > 0) {
                foreach (AstInheritsFrom tag in InheritsFrom) {
                    xml.WriteElementString("inheritsfrom", tag.ToString());
                }
            }
            if (IsAction) {
                xml.WriteStartElement("action");
                if (IsAsync) {
                    xml.WriteAttributeString("async", "true");
                }
                if (IsAjax) {
                    xml.WriteAttributeString("ajax", "true");
                }
                xml.WriteEndElement();
            }
            if (Constant != null) {
                xml.WriteElementString("constant", Convert.ToString(Constant));
            }
            if (Expression != null) {
                xml.WriteElementString("expression", Expression.ToString());
            }
            if (Query != null) {
                xml.WriteElementString("query", Query.ToString());
            }
            if (Children.Count > 0) {
                foreach (AstNode child in Children) {
                    child.WriteXmlRepresentation(xml);
                }
            }
            xml.WriteEndElement();
        }

        public override string ToString() {
            StringBuilder sb = new StringBuilder();
            if (IsAction) {
               sb.Append(" -> ");
                if (IsAsync) {
                    sb.Append("async ");
                }
                if (IsAjax) {
                    sb.Append("ajax ");
                }
            }
            if (Tag != null) {
                sb.Append(Tag.ToString());
            }
            if (InheritsFrom.Count > 0) {
                sb.Append(" : ");
                foreach (AstInheritsFrom tag in InheritsFrom) {
                    sb.Append(tag.ToString()).Append(", ");
                }
                sb.Length = sb.Length - 2;
            }
            if (Constant != null) {
                sb.AppendLine().AppendLine(Convert.ToString(Constant));
            }
            if (Expression != null) {
                sb.AppendLine().AppendLine(Expression.ToString());
            }
            if (Query != null) {
                sb.AppendLine().AppendLine(Query.ToString());
            }
            if (Children.Count > 0) {
                sb.AppendLine(" {");
                foreach (AstNode child in Children) {
                    sb.AppendLine(child.ToString());
                }
                sb.AppendLine("}");
            }
            sb.AppendLine();
            return sb.ToString();
        }

    }

}
